#include "scene.h"
#include <cmath>
#include <GL/gl.h>
#include "loop.h"
#include <iostream>

Scene::Scene(){
    selectedColor = Color(1, 0.0, 0.0);
}

Scene::~Scene(){
    for(std::vector<Solid *>::iterator itS = solids.begin(); itS != solids.end(); ++itS){
        delete (*itS);
    }
}

void Scene::addSolid(Solid *_s){
    solids.push_back(_s);
}

void Scene::deleteSolid(Solid *_s){
    int size = solids.size();
    for (int i = size; i > 0; i--){
        if ( solids.at(i - 1) == _s ){
            solids.erase(solids.begin() + i - 1);
        }
    }

    size = selectedSolids.size();
    for (int i = size; i > 0; i--){
        if ( selectedSolids.at(i - 1) == _s ){
            selectedSolids.erase(selectedSolids.begin() + i - 1);
        }
    }

    size = selectedFaces.size();
    for (int i = size; i > 0; i--){
        if ( selectedFaces.at(i - 1)->getSolid() == _s ){
            selectedFaces.erase(selectedFaces.begin() + i - 1);
        }
    }

    size = selectedEdges.size();
    for (int i = size; i > 0; i--){
        if ( selectedEdges.at(i - 1)->getHE1()->getLoop()->getFace()->getSolid() == _s ){
            selectedEdges.erase(selectedEdges.begin() + i - 1);
        }
    }

    size = selectedVertices.size();
    for (int i = size; i > 0; i--){
        if ( selectedVertices.at(i - 1)->getHE()->getLoop()->getFace()->getSolid() == _s ){
            selectedVertices.erase(selectedVertices.begin() + i - 1);
        }
    }
}

void Scene::addSelectedSolid(Solid *_s, bool _selection){
    int size;

    _s->select(_selection);
    if (_selection) selectedSolids.push_back(_s);
    else {
        size = selectedSolids.size();
        for (int i = size; i > 0; i--){
            if ( selectedSolids.at(i - 1) == _s ){
                selectedSolids.erase(selectedSolids.begin() + i - 1);
            }
        }
    }
}

void Scene::addSelectedFace(Face *_f, bool _selection){
    int size;

    _f->select(_selection);
    if (_selection) selectedFaces.push_back(_f);
    else {
        size = selectedFaces.size();
        for (int i = size; i > 0; i--){
            if ( selectedFaces.at(i - 1) == _f ){
                selectedFaces.erase(selectedFaces.begin() + i - 1);
            }
        }
    }
}

void Scene::addSelectedEdge(Edge *_e, bool _selection){
    int size;

    _e->select(_selection);
    if (_selection) selectedEdges.push_back(_e);
    else {
        size = selectedEdges.size();
        for (int i = size; i > 0; i--){
            if ( selectedEdges.at(i - 1) == _e ){
                selectedEdges.erase(selectedEdges.begin() + i - 1);
            }
        }
    }
}

void Scene::addSelectedVertex(Vertex *_v, bool _selection){
    int size;

    _v->select(_selection);
    if (_selection) selectedVertices.push_back(_v);
    else {
        size = selectedVertices.size();
        for (int i = size; i > 0; i--){
            if ( selectedVertices.at(i - 1) == _v ){
                selectedVertices.erase(selectedVertices.begin() + i - 1);
            }
        }
    }
}

void Scene::addSelectedPoint(Point *_p, bool _selection){
    int size;

    _p->select(_selection);
    if (_selection) selectedPoints.push_back(_p);
    else {
        size = selectedPoints.size();
        for (int i = size; i > 0; i--){
            if ( selectedPoints.at(i - 1) == _p ){
                selectedPoints.erase(selectedPoints.begin() + i - 1);
            }
        }
    }
}

void Scene::selectAdjacentVertices(std::vector<Vertex *> *_selected){
    selectAdjacentVV(_selected);
    selectAdjacentSV(_selected);
    selectAdjacentFV(_selected);
    selectAdjacentEV(_selected);

    selectedSolids.clear();
    selectedFaces.clear();
    selectedEdges.clear();

    selectedVertices.insert(selectedVertices.end(), _selected->begin(), _selected->end());
}

void Scene::selectAdjacentVV(std::vector<Vertex *> *_selected){
    HalfEdge *he;
    Vertex *v;
    for(std::vector<Vertex *>::iterator itS = selectedVertices.begin(); itS != selectedVertices.end(); itS++){
        he = (*itS)->getHE();
        do{
            if( !( (v = he->getTwin()->getStart())->isSelected() ) ){
                _selected->push_back(v);
                v->select(true);
            }
            he = he->getTwin()->getNext();
        }while( he != (*itS)->getHE() );
    }
}

void Scene::selectAdjacentEV(std::vector<Vertex *> *_selected){
    Vertex *v;
    for(std::vector<Edge *>::iterator itS = selectedEdges.begin(); itS != selectedEdges.end(); itS++){
        if( !( (v = (*itS)->getHE1()->getStart())->isSelected() ) ){
            _selected->push_back(v);
            v->select(true);
        }
        if( !( (v = (*itS)->getHE2()->getStart())->isSelected() ) ){
            _selected->push_back(v);
            v->select(true);
        }

        (*itS)->select(false);
    }
}

void Scene::selectAdjacentFV(std::vector<Vertex *> *_selected){
    HalfEdge *he;
    Vertex *v;
    for(std::vector<Face *>::iterator itS = selectedFaces.begin(); itS != selectedFaces.end(); itS++){
        he = (*itS)->getLoop()->getHERing();
        do{
            if( !( (v = he->getStart())->isSelected() ) ){
                _selected->push_back(v);
                v->select(true);
            }
            he = he->getNext();
        }while( he != (*itS)->getLoop()->getHERing() );

        (*itS)->select(false);
    }
}

void Scene::selectAdjacentSV(std::vector<Vertex *> *_selected){
    Vertex *v;
    for(std::vector<Solid *>::iterator itS = selectedSolids.begin(); itS != selectedSolids.end(); itS++){
        for(int i = 0; i < (*itS)->sizeVertices(); i++){
             if( !( (v = (*itS)->getVertix(i))->isSelected() ) ){
                _selected->push_back(v);
                v->select(true);
             }
        }
        (*itS)->select(false);
    }
}

void Scene::selectAdjacentEdges(std::vector<Edge *> *_selected){
    selectAdjacentEE(_selected);
    selectAdjacentSE(_selected);
    selectAdjacentFE(_selected);
    selectAdjacentVE(_selected);

    selectedSolids.clear();
    selectedFaces.clear();
    selectedVertices.clear();

    selectedEdges.insert(selectedEdges.end(), _selected->begin(), _selected->end());
}

void Scene::selectAdjacentVE(std::vector<Edge *> *_selected){
    HalfEdge *he;
    Edge *e;
    for(std::vector<Vertex *>::iterator itS = selectedVertices.begin(); itS != selectedVertices.end(); itS++){
        he = (*itS)->getHE();
        do{
            if( !( (e = he->getEdge())->isSelected() ) ){
                _selected->push_back(e);
                e->select(true);
            }
            he = he->getTwin()->getNext();
        }while( he != (*itS)->getHE() );

        (*itS)->select(false);
    }
}

void Scene::selectAdjacentEE(std::vector<Edge *> *_selected){
    Edge *e;
    HalfEdge *he;
    for(std::vector<Edge *>::iterator itS = selectedEdges.begin(); itS != selectedEdges.end(); itS++){
        he = (*itS)->getHE2()->getNext();
        do{
            if( !( (e = he->getEdge())->isSelected() ) ){
                _selected->push_back(e);
                e->select(true);
            }
            he = he->getTwin()->getNext();
        }while( he != (*itS)->getHE1() );

        he = (*itS)->getHE1()->getNext();
        do{
            if( !( (e = he->getEdge())->isSelected() ) ){
                _selected->push_back(e);
                e->select(true);
            }
            he = he->getTwin()->getNext();
        }while( he != (*itS)->getHE2() );
    }
}

void Scene::selectAdjacentFE(std::vector<Edge *> *_selected){
    Edge *e;
    HalfEdge *he;
    for(std::vector<Face *>::iterator itS = selectedFaces.begin(); itS != selectedFaces.end(); itS++){
        he = (*itS)->getLoop()->getHERing();
        do{
            if( !( (e = he->getEdge())->isSelected() ) ){
                _selected->push_back(e);
                e->select(true);
            }
            he = he->getNext();
        }while( he != (*itS)->getLoop()->getHERing() );

        (*itS)->select(false);
    }
}

void Scene::selectAdjacentSE(std::vector<Edge *> *_selected){
    Edge *e;
    for(std::vector<Solid *>::iterator itS = selectedSolids.begin(); itS != selectedSolids.end(); itS++){
        for(int i = 0; i < (*itS)->sizeEdges(); i++){
             if( !( (e = (*itS)->getEdge(i))->isSelected() ) ){
                _selected->push_back(e);
                e->select(true);
             }
        }
        (*itS)->select(false);
    }
}

void Scene::selectAdjacentFaces(std::vector<Face *> *_selected){
    selectAdjacentFF(_selected);
    selectAdjacentSF(_selected);
    selectAdjacentEF(_selected);
    selectAdjacentVF(_selected);

    selectedSolids.clear();
    selectedEdges.clear();
    selectedVertices.clear();

    selectedFaces.insert(selectedFaces.end(), _selected->begin(), _selected->end());
}

void Scene::selectAdjacentVF(std::vector<Face *> *_selected){
    HalfEdge *he;
    Face *f;
    for(std::vector<Vertex *>::iterator itS = selectedVertices.begin(); itS != selectedVertices.end(); itS++){
        he = (*itS)->getHE();
        do{
            if( !( (f = he->getLoop()->getFace())->isSelected() ) ){
                _selected->push_back(f);
                f->select(true);
            }
            he = he->getTwin()->getNext();
        }while( he != (*itS)->getHE() );

        (*itS)->select(false);
    }
}

void Scene::selectAdjacentEF(std::vector<Face *> *_selected){
    Face *f;
    for(std::vector<Edge *>::iterator itS = selectedEdges.begin(); itS != selectedEdges.end(); itS++){
        if( !( (f = (*itS)->getHE1()->getLoop()->getFace() )->isSelected() ) ){
            _selected->push_back(f);
            f->select(true);
        }

        if( !( (f = (*itS)->getHE2()->getLoop()->getFace() )->isSelected() ) ){
            _selected->push_back(f);
            f->select(true);
        }

        (*itS)->select(false);
    }
}

void Scene::selectAdjacentFF(std::vector<Face *> *_selected){
    Face *f;
    HalfEdge *he;
    for(std::vector<Face *>::iterator itS = selectedFaces.begin(); itS != selectedFaces.end(); itS++){
        he = (*itS)->getLoop()->getHERing();
        do{
            if( !( (f = he->getTwin()->getLoop()->getFace())->isSelected() ) ){
                _selected->push_back(f);
                f->select(true);
            }
            he = he->getNext();
        }while( he != (*itS)->getLoop()->getHERing() );
    }
}

void Scene::selectAdjacentSF(std::vector<Face *> *_selected){
    Face *f;
    for(std::vector<Solid *>::iterator itS = selectedSolids.begin(); itS != selectedSolids.end(); itS++){
        for(int i = 0; i < (*itS)->sizeFaces(); i++){
             if( !( (f = (*itS)->getFace(i))->isSelected() ) ){
                _selected->push_back(f);
                f->select(true);
             }
        }

        (*itS)->select(false);
    }
}

void Scene::selectAdjacentSolids(std::vector<Solid *> *_selected){
    selectAdjacentSS(_selected);
    selectAdjacentFS(_selected);
    selectAdjacentES(_selected);
    selectAdjacentVS(_selected);

    selectedFaces.clear();
    selectedEdges.clear();
    selectedVertices.clear();

    selectedSolids.insert(selectedSolids.end(), _selected->begin(), _selected->end());
}

void Scene::selectAdjacentVS(std::vector<Solid *> *_selected){
    Solid *s;
    for(std::vector<Vertex *>::iterator itS = selectedVertices.begin(); itS != selectedVertices.end(); itS++){
        if( !( (s = (*itS)->getHE()->getLoop()->getFace()->getSolid())->isSelected() ) ){
            _selected->push_back(s);
            s->select(true);
        }

        (*itS)->select(false);
    }
}

void Scene::selectAdjacentES(std::vector<Solid *> *_selected){
    Solid *s;
    for(std::vector<Edge *>::iterator itS = selectedEdges.begin(); itS != selectedEdges.end(); itS++){
        if( !( (s = (*itS)->getHE1()->getLoop()->getFace()->getSolid() )->isSelected() ) ){
            _selected->push_back(s);
            s->select(true);
        }

        (*itS)->select(false);
    }
}

void Scene::selectAdjacentFS(std::vector<Solid *> *_selected){
    Solid *s;
    for(std::vector<Face *>::iterator itS = selectedFaces.begin(); itS != selectedFaces.end(); itS++){
        if( !( (s = (*itS)->getSolid())->isSelected() ) ){
            _selected->push_back(s);
            s->select(true);
        }

        (*itS)->select(false);
    }
}

void Scene::selectAdjacentSS(std::vector<Solid *> *_selected){
    for(std::vector<Solid *>::iterator itS = selectedSolids.begin(); itS != selectedSolids.end(); itS++){
        if( ( (*itS)->isSelected() ) ){
            _selected->push_back(*itS);
            (*itS)->select(true);
        }
    }
}

Solid* Scene::getSolid(int i){
    return solids.at(i);
}

int Scene::sizeSolids(){
    return solids.size();
}

void Scene::scale(double _s){
    for(std::vector<Solid *>::iterator itS = selectedSolids.begin(); itS != selectedSolids.end(); itS++){
        (*itS)->scale(_s);
    }
    for(std::vector<Face*>::iterator itS = selectedFaces.begin(); itS != selectedFaces.end(); itS++){
        (*itS)->scale(_s);
    }
    for(std::vector<Edge*>::iterator itS = selectedEdges.begin(); itS != selectedEdges.end(); itS++){
        (*itS)->scale(_s);
    }
    for(std::vector<Vertex*>::iterator itS = selectedVertices.begin(); itS != selectedVertices.end(); itS++){
        (*itS)->scale(_s);
    }
}

void Scene::translate(Point _t){//ref == 0 => X    |    ref == 1 => Y    |    ref == 2 => Z
    for(std::vector<Solid *>::iterator itS = selectedSolids.begin(); itS != selectedSolids.end(); itS++){
        (*itS)->translate(_t);
    }
    for(std::vector<Face*>::iterator itS = selectedFaces.begin(); itS != selectedFaces.end(); itS++){
        (*itS)->translate(_t);
    }
    for(std::vector<Edge*>::iterator itS = selectedEdges.begin(); itS != selectedEdges.end(); itS++){
        (*itS)->translate(_t);
    }
    for(std::vector<Vertex*>::iterator itS = selectedVertices.begin(); itS != selectedVertices.end(); itS++){
        (*itS)->translate(_t);
    }
}

bool Scene::changeColor(Color _c){
    if (!selectedVertices.empty() || !selectedEdges.empty() || !selectedFaces.empty()) return false;
    if (selectedSolids.empty()) return false;
    else{
        for(std::vector<Solid *>::iterator itS = selectedSolids.begin(); itS != selectedSolids.end(); itS++){
            (*itS)->setColor(_c);
        }
    }

    return true;
}

bool Scene::sweep(Point _p){
    if (!selectedVertices.empty() || !selectedEdges.empty() || !selectedSolids.empty()) return false;
    if (selectedFaces.empty()) return false;
    else{
        for(std::vector<Face*>::iterator itS = selectedFaces.begin(); itS != selectedFaces.end(); itS++){
            euler.sweep((*itS), _p);
        }
    }

    return true;
}

bool Scene::toBezier(){
    if (!selectedVertices.empty() || !selectedEdges.empty() || !selectedSolids.empty()) return false;
    if (selectedFaces.empty() || selectedFaces.size() > 1) return false;
    else{
        Face *f_ = selectedFaces.at(0);
        if(!f_->isBezier()) f_->setBezier(4, 0.1);
        else return false;
    }

    return true;
}

void Scene::movePoints(Point _p){
    if (!selectedVertices.empty() || !selectedEdges.empty() || !selectedSolids.empty()) return;
    if (selectedFaces.empty() || selectedFaces.size() > 1) return;
    if (selectedPoints.empty()) return;

    Point **pt, *p;
    for(std::vector<Point *>::iterator itS = selectedPoints.begin(); itS != selectedPoints.end(); itS++){
        pt = (&(*itS));
//std::cout <<"\n\nantes: "; (*itS)->show();
//std::cout <<"soma: "; _p.show();
//std::cout << "pt: "  << pt << "  - p: "<< (*pt) <<std::endl;
        p = _p + (*itS);
        p->select(true);
        //delete (*itS);
        (**pt) = *p;
        //std::cout << "pt: "  << pt << "  - p: "<< (*pt) <<std::endl;//"  - c: ";
        //(**pt).show();

//std::cout <<"\n\ndepois: "; (*pt)->show(); (*itS)->show();
    }

    selectedFaces.at(0)->getBezier()->calculate();
}

bool Scene::analyseArea(double* _area){
    if (!selectedVertices.empty() || !selectedEdges.empty()) return false;
    if (!selectedFaces.empty() && !selectedSolids.empty()) return false;
    if (selectedFaces.empty()){
        if (selectedSolids.empty()){
            return false;
        }
        else{
            for(std::vector<Solid *>::iterator itS = selectedSolids.begin(); itS != selectedSolids.end(); itS++){
                (*_area) += (*itS)->area();
            }
        }
    }
    else
        for(std::vector<Face*>::iterator itS = selectedFaces.begin(); itS != selectedFaces.end(); itS++){
            (*_area) += (*itS)->area();
        }

    return true;
}

Solid *Scene::makeBox(){
    Solid *s = euler.mvfs(Point (-1.0, -1.0, -1.0));
    euler.mev(s, s->getFace(0), s->getVertix(0), s->getVertix(0), Point( 1.0, -1.0, -1.0));
    euler.mev(s, s->getFace(0), s->getVertix(1), s->getVertix(0), Point( 1.0, -1.0,  1.0));
    euler.mev(s, s->getFace(0), s->getVertix(2), s->getVertix(1), Point(-1.0, -1.0,  1.0));
    euler.mef(s, s->getFace(0), s->getVertix(0), s->getVertix(3));

    euler.mev(s, s->getFace(0), s->getVertix(0), s->getVertix(3), Point(-1.0,  1.0, -1.0));
    euler.mev(s, s->getFace(0), s->getVertix(4), s->getVertix(0), Point( 1.0,  1.0, -1.0));
    euler.mef(s, s->getFace(0), s->getVertix(1), s->getVertix(5));

    euler.mev(s, s->getFace(0), s->getVertix(5), s->getVertix(4), Point( 1.0,  1.0,  1.0));
    euler.mef(s, s->getFace(0), s->getVertix(2), s->getVertix(6));

    euler.mev(s, s->getFace(0), s->getVertix(6), s->getVertix(5), Point(-1.0,  1.0,  1.0));
    euler.mef(s, s->getFace(0), s->getVertix(3), s->getVertix(7));
    euler.mef(s, s->getFace(0), s->getVertix(4), s->getVertix(7));

    solids.push_back(s);
    return s;
}

Solid *Scene::makeCorner(){
    Solid *s = euler.mvfs(Point (-1.0, -1.0, -1.0));
    euler.mev(s, s->getFace(0), s->getVertix(0), s->getVertix(0), Point( 1.0, -1.0, -1.0));
    euler.mev(s, s->getFace(0), s->getVertix(1), s->getVertix(0), Point( 1.0, -1.0,  1.0));
    euler.mev(s, s->getFace(0), s->getVertix(2), s->getVertix(1), Point(-1.0, -1.0,  1.0));
    euler.mef(s, s->getFace(0), s->getVertix(0), s->getVertix(3));

    euler.mev(s, s->getFace(0), s->getVertix(0), s->getVertix(3), Point(-1.0,  1.0, -1.0));
    euler.mev(s, s->getFace(0), s->getVertix(4), s->getVertix(0), Point( 1.0,  1.0, -1.0));
    euler.mef(s, s->getFace(0), s->getVertix(1), s->getVertix(5));

    euler.mev(s, s->getFace(0), s->getVertix(4), s->getVertix(0), Point(-1.0,  1.0,  0.0));
    euler.mev(s, s->getFace(0), s->getVertix(6), s->getVertix(4), Point(-1.0,  0.0,  0.0));
    euler.mef(s, s->getFace(0), s->getVertix(7), s->getVertix(0));

    euler.mev(s, s->getFace(0), s->getVertix(7), s->getVertix(0), Point(-1.0,  0.0,  1.0));
    euler.mef(s, s->getFace(0), s->getVertix(8), s->getVertix(3));

    euler.mev(s, s->getFace(0), s->getVertix(8), s->getVertix(3), Point( 1.0,  0.0,  1.0));
    euler.mef(s, s->getFace(0), s->getVertix(9), s->getVertix(2));

    euler.mev(s, s->getFace(0), s->getVertix(9), s->getVertix(2), Point( 1.0,  0.0,  0.0));
    euler.mef(s, s->getFace(0), s->getVertix(7), s->getVertix(10));
    euler.mef(s, s->getFace(0), s->getVertix(10), s->getVertix(1));

    euler.mev(s, s->getFace(0), s->getVertix(10),s->getVertix(1), Point( 1.0,  1.0,  0.0));
    euler.mef(s, s->getFace(0), s->getVertix(11), s->getVertix(5));
    euler.mef(s, s->getFace(0), s->getVertix(6), s->getVertix(11));

    solids.push_back(s);
    return s;
}

Solid *Scene::makeSphere(){
	double passo = 20, passo1 = 20;
	double beta, alfa, radius = 2.0, h = 80;


//polo de cima
    beta = h*M_PI/180.0;
    Solid *s = euler.mvfs(Point (0, radius, 0));

    alfa = 0.0;
    euler.mev(s, s->getFace(0), s->getVertix(0), s->getVertix(0),
              Point(radius*cos(alfa)*cos(beta), radius*sin(beta), radius*sin(alfa)*cos(beta)));

    for(alfa = passo*M_PI/180.0; alfa <= (360-passo)*M_PI/180.0; alfa += passo*M_PI/180.0){
        euler.mev(s, s->getFace(0), s->getVertix(0), s->getVertix(1),
                  Point(radius*cos(alfa)*cos(beta), radius*sin(beta), radius*sin(alfa)*cos(beta)));
        euler.mef(s, s->getFace(0), s->getSecondLastVertix(), s->getLastVertix());
    }
    euler.mef(s, s->getFace(0), s->getLastVertix(), s->getVertix(1));


//centro
    double size = 360.0/passo;
    int current;

    for(beta = (h - passo1)*M_PI/180.0; beta >= -(h + passo1)*M_PI/180.0; beta -= passo1*M_PI/180.0 ){
        alfa = 0.0;
		current = s->sizeVertices() - size;

        euler.mev(s, s->getFace(0), s->getVertix(current), s->getVertix(current + 1),
              Point(radius*cos(alfa)*cos(beta), radius*sin(beta), radius*sin(alfa)*cos(beta)));


        for(alfa = (passo)*M_PI/180.0, current++; alfa < (360-(2*passo))*M_PI/180.0; alfa += passo*M_PI/180.0, current++){
            euler.mev(s, s->getFace(0), s->getVertix(current), s->getVertix(current + 1),
                  Point(radius*cos(alfa)*cos(beta), radius*sin(beta), radius*sin(alfa)*cos(beta)));
            euler.mef(s, s->getFace(0), s->getSecondLastVertix(), s->getLastVertix());
        }
        euler.mev(s, s->getFace(0), s->getVertix(current), s->getVertix(s->sizeVertices() - (2*size) + 1),
              Point(radius*cos(alfa)*cos(beta), radius*sin(beta), radius*sin(alfa)*cos(beta)));
        euler.mef(s, s->getFace(0), s->getSecondLastVertix(), s->getLastVertix());
        euler.mef(s, s->getFace(0), s->getLastVertix(), s->getVertix(s->sizeVertices() - size));
	}


//polo de baixo
    beta = -h*M_PI/180.0;

    alfa = 0.0;
    current = s->sizeVertices() - size;

    euler.mev(s, s->getFace(0), s->getLastVertix(), s->getVertix(current),
              Point(0.0, -radius, 0.0));

    for(alfa = passo*M_PI/180.0; alfa <= (360-passo)*M_PI/180.0; alfa += passo*M_PI/180.0, current++){
        euler.mef(s, s->getFace(0), s->getLastVertix(), s->getVertix(current));
    }

    solids.push_back(s);
    return s;
}

void Scene::draw(unsigned int show, bool wireframe, bool controlPoints){
    HalfEdge *he = NULL;
    Loop *l = NULL;
    int faces;
    BezierSurface *b;
    Point *p;
    int size;

    for(std::vector<Solid*>::iterator itS = solids.begin(); itS != solids.end(); ++itS){
        faces = (*itS)->sizeFaces();
        for(int f = 0; f < faces; f++){

            l = (*itS)->getFace(f)->getLoop();

            switch(show){
                case 0 : //tudo que tiver selecionado
                    if ((*itS)->getFace(f)->isSelected())
                        drawFace((*itS)->getFace(f));

                    he = l->getHERing();

                    do{
                        if (he->getStart()->isSelected())
                            drawVertex(he->getStart());

                        if (he->getEdge()->isSelected())
                            drawEdge(he->getEdge());

                        he = he->getNext();
                    }while (he != l->getHERing());

                    if (wireframe){
                        glColor3f(0, 0, 0);
                        glBegin(GL_LINE_LOOP);
                            he = l->getHERing();
                            do{
                                glVertex3dv( he->getStart()->getPointVector() );
                                he = he->getNext();
                            }while (he != l->getHERing());
                        glEnd();
                    }

                    break;

                case 1 : //vertices
                    he = l->getHERing();
                    do{
                        drawVertex(he->getStart());
                        he = he->getNext();
                    }while (he != l->getHERing());

                    break;

                case 2 : //arestas
                    he = l->getHERing();
                    do{
                        drawEdge(he->getEdge());
                        he = he->getNext();
                    }while (he != l->getHERing());

                    break;

                case 3 : //faces
                    if ((*itS)->getFace(f)->isSelected())
                        drawFace((*itS)->getFace(f));

                    glLineWidth(3);
                    glColor3f(0, 0, 0);
                    glBegin(GL_LINE_LOOP);
                        he = l->getHERing();
                        do{
                            glVertex3dv( he->getStart()->getPointVector() );
                            he = he->getNext();
                        }while (he != l->getHERing());
                    glEnd();

                    break;
            }


            if (controlPoints && (*itS)->getFace(f)->isBezier()){
                glPointSize(3);
                b = (*itS)->getFace(f)->getBezier();

                glBegin(GL_POINTS);
                    size = b->getSizeControl();
                    for(int i = 0; i < size; i++){
                        for(int j = 0; j < size; j++){
                            p = b->getControlPoint(i, j);

                            if (p->isSelected()) glColor3f(1, 1, 0);
                            else glColor3f(0,0,0);
                            glVertex3d(p->x, p->y, p->z);
                        }
                    }
                glEnd();
            }


            if (!wireframe){
                drawFace((*itS)->getFace(f));
            }
            else if ((*itS)->isSelected())
                    drawFace((*itS)->getFace(f));
        }
    }
}

void Scene::drawFace(Face *f){
    if (f->isSelected() || f->getSolid()->isSelected()) glColor3f(selectedColor.red, selectedColor.green, selectedColor.blue);
    else{
        Color c = f->getSolid()->getColor();
        glColor3f(c.red, c.green, c.blue);
    }

    if(f->isBezier()){
        BezierSurface *b = f->getBezier();
        Point q1, q2, q3, q4;
        int size = b->getSizePoints();

        glBegin(GL_QUADS);
            for(int v = 0; v < size - 1; v++){
                for(int u = 0; u < size-1; u++){
                    q1 = b->getPoint(u, v);
                    q2 = b->getPoint(u, v+1);
                    q4 = b->getPoint(u+1, v);

                    q3 = ((q4 - q1).crossProduct(q2 - q1)).normalization();
                    glNormal3d(q3.x, q3.y, q3.z);

                    q3 = b->getPoint(u+1, v+1);

                    glVertex3d(q1.x, q1.y, q1.z);
                    glVertex3d(q2.x, q2.y, q2.z);
                    glVertex3d(q3.x, q3.y, q3.z);
                    glVertex3d(q4.x, q4.y, q4.z);
                }
            }
        glEnd();
    }
    else{
        HalfEdge *he, *lHE;
        he = lHE = f->getLoop()->getHERing();

        glNormal3dv(f->getNormalVector());
        glBegin(GL_POLYGON);
            do{
                glVertex3dv( he->getStart()->getPointVector() );
                he = he->getNext();
            }while (he != lHE);
        glEnd();
    }
}

void Scene::drawEdge(Edge *e){
    if (e->isSelected()) glColor3f(selectedColor.red, selectedColor.green, selectedColor.blue);
    else glColor3f(0, 0, 0);

    glLineWidth(2);
    glBegin(GL_LINES);
        glVertex3dv( e->getHE1()->getStart()->getPointVector() );
        glVertex3dv( e->getHE2()->getStart()->getPointVector() );
    glEnd();
    glLineWidth(1);
}

void Scene::drawVertex(Vertex *v){
    if (v->isSelected()) glColor3f(selectedColor.red, selectedColor.green, selectedColor.blue);
    else glColor3f(0, 0, 0);

    glPointSize(3);
    glBegin(GL_POINTS);
        glVertex3dv( v->getPointVector() );
    glEnd();
    glPointSize(1);
}

void Scene::print(){
    HalfEdge *he = NULL;
    Loop *l = NULL;
    int faces;
    Color color;

    for(std::vector<Solid*>::iterator itS = solids.begin(); itS != solids.end(); ++itS){
        faces = (*itS)->sizeFaces();
        for(int f = 0; f < faces; f++){
            Point n = (*itS)->getFace(f)->getNormal();
            std::cout << "face " << (*itS)->getFace(f)->getID() << "  normal: (" << n.x << ", " << n.y << ", " << n.z << ")" << std::endl;
            std::cout << "loop ";

            l = (*itS)->getFace(f)->getLoop();

            he = l->getHERing();
            do{
                std::cout << he->getID() << "  ";
                he = he->getNext();
            }while (he != l->getHERing());
            std::cout << std::endl << std::endl << std::endl;
        }
    }
}
